package com.lyxs916.widget.loading.bar;

import android.app.Activity;
import android.content.Context;
import android.support.annotation.LayoutRes;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;

import com.lyxs916.widget.loading.LoadingConfig;
import com.lyxs916.widget.loading.factory.LoadingFactory;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


/**
 * 说明:加载进度 * <p>可用于FrameLayout、RelativeLayout、DrawerLayout、CoordinatorLayout、CardView<p>
 * 如果不的以上的VoidGroup,mParent会一直向上寻找
 * <p>
 * 作者： 杨阳; 创建于：  2017-06-08  19:42
 */
public final class LoadingBar implements ILoadingBar {
    //存放创建的对象
    private static final Map<View, LoadingBar> LOADING_BARS = new HashMap<>();
    private static int LOADING_LIMIT = 15;//默认15,超过会检查资源释放
    //传入的view
    private ViewGroup mParent;
    //父类的view
    private View mView;
    //回调
    private OnLoadingBarListener mListener;

    private LoadingBar(ViewGroup parent, LoadingFactory factory) {
        mParent = parent;
        mView = factory.onCreateView(mParent);
    }


    /**
     * 显示loading
     */
    @Override
    public void show() {
        if (mView != null) {
            mView.setVisibility(View.VISIBLE);
            if (mView.getParent() != null) {
                mParent.removeView(mView);
            }
            mParent.addView(mView);
        }
    }

    /**
     * 取消loading
     */
    @Override
    public void cancel() {
        if (mView != null) {
            mView.setVisibility(View.GONE);
            mParent.removeView(mView);
            mView = null;
            if (this.mListener != null) {
                this.mListener.onCancel(mParent);
            }
        }
    }

    public LoadingBar setOnClickListener(View.OnClickListener listener) {
        if (mView != null) {
            mView.setOnClickListener(listener);
        }
        return this;
    }

    public LoadingBar setOnLoadingBarListener(OnLoadingBarListener mListener) {
        this.mListener = mListener;
        return this;
    }

    /**
     * 布置显示的位置, 默认的bar
     * <p>
     * <p>可用于FrameLayout、RelativeLayout、DrawerLayout、CoordinatorLayout、CardView<p>
     * 如果不的以上的VoidGroup,mParent会一直向上寻找
     *
     * @param parent 依赖显示的View
     * @return LoadingBar
     */
    public static LoadingBar make(View parent) {
        return make(parent, LoadingConfig.getLoadingFactory());
    }

    /**
     * 布置显示的位置（自定义的View）
     *
     * @param parent  依赖显示的View
     * @param factory 要显示的View
     * @return
     */
    public static LoadingBar make(View parent, LoadingFactory factory) {
        //如果已经有Loading在显示了,如果已经显示则移除
        if (LOADING_BARS.containsKey(parent)) {
            LoadingBar loadingBar = LOADING_BARS.get(parent);
            loadingBar.mParent.removeView(loadingBar.mView);
        }
        LoadingBar newLoadingBar = new LoadingBar(findSuitableParent(parent), factory);
        LOADING_BARS.put(parent, newLoadingBar);
        return newLoadingBar;
    }

    /**
     * 说明:布置显示的位置, 自定义bar
     * 作者： 杨阳; 创建于：  2017-06-08  21:09
     *
     * @param parent   依赖显示的View
     * @param layoutId 要显示的View
     * @return
     */
    public static LoadingBar make(View parent, final @LayoutRes int layoutId) {
        try {
            LoadingFactory lf = new LoadingFactory() {
                @Override
                public View onCreateView(ViewGroup parent) {
                    return LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
                }
            };
            return make(parent, lf);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return make(parent);
    }

    /**
     * 根据父节点取消单个loading
     *
     * @param parent show传过来的父节点
     */
    public static void cancel(View parent) {
        LoadingBar loadingBar = LOADING_BARS.get(parent);
        if (loadingBar != null) {
            loadingBar.cancel();
        }
        LOADING_BARS.remove(parent);
    }

    /**
     * 取消所有loading
     */
    private static void cancelAll() {
        Iterator<Map.Entry<View, LoadingBar>> it = LOADING_BARS.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<View, LoadingBar> entry = it.next();
            cancel(entry.getKey());
        }
    }

    /**
     * 释放无用的资源
     */
    public static void release() {
        release(LOADING_LIMIT);
    }

    /**
     * 释放无用的资源
     * <p>可在BaseActivity onDestroy调用</p>
     *
     * @param limit loading池的限制,超过数量才检查资源释放
     */
    public static void release(int limit) {
        if (limit <= 0) {
            limit = LOADING_LIMIT;
        }
        if (LOADING_BARS.size() < limit) {
            return;
        }
        Log.d("LoadingBar", "release before loading size - " + LOADING_BARS.size());
        Iterator<Map.Entry<View, LoadingBar>> it = LOADING_BARS.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<View, LoadingBar> entry = it.next();
            Context context = entry.getKey().getContext();
            if (context instanceof Activity && ((Activity) context).isFinishing()) {
                it.remove();
            }
        }
        Log.d("LoadingBar", "release after loading size - " + LOADING_BARS.size());
    }

    /**
     * 找到合适的父布局
     *
     * @param parent
     * @return
     */
    private static ViewGroup findSuitableParent(View parent) {
        if (parent == null) {
            return null;
        }
        View suitableParent = parent;
        do {
            if (suitableParent instanceof FrameLayout || suitableParent instanceof RelativeLayout ||
                    "android.support.v4.widget.DrawerLayout".equals(suitableParent.getClass().getName()) ||
                    "android.support.design.widget.CoordinatorLayout".equals(suitableParent.getClass().getName()) ||
                    "android.support.v7.widget.CardView".equals(suitableParent.getClass().getName())) {
                return (ViewGroup) suitableParent;
            } else {
                final ViewParent viewParent = suitableParent.getParent();
                suitableParent = viewParent instanceof View ? (View) viewParent : null;
                return (ViewGroup) suitableParent;
            }
        } while (suitableParent != null);
    }

}
